package cn.edu.scnu.gansenbang.conanliu;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Properties;

import com.hp.hpl.jena.db.DBConnection;
import com.hp.hpl.jena.db.IDBConnection;
import com.hp.hpl.jena.ontology.Individual;
import com.hp.hpl.jena.ontology.OntClass;
import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.ontology.OntModelSpec;
import com.hp.hpl.jena.ontology.OntProperty;
import com.hp.hpl.jena.ontology.OntResource;
import com.hp.hpl.jena.query.Query;
import com.hp.hpl.jena.query.QueryExecution;
import com.hp.hpl.jena.query.QueryExecutionFactory;
import com.hp.hpl.jena.query.QueryFactory;
import com.hp.hpl.jena.query.QuerySolution;
import com.hp.hpl.jena.query.ResultSet;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.ModelMaker;
import com.hp.hpl.jena.rdf.model.Property;
import com.hp.hpl.jena.rdf.model.Statement;
import com.hp.hpl.jena.rdf.model.StmtIterator;
import com.hp.hpl.jena.rdf.model.impl.StatementImpl;
import com.hp.hpl.jena.util.iterator.ExtendedIterator;

public class DBStore {
	 private final static String strDriver = "com.mysql.jdbc.Driver"; // path of driver class
	 //private final static String strURL = "jdbc:mysql://localhost:3306/jena_test";
	 //private final static String user = "root";
	 //private final static String passwd = "";
	 private static final String strDB = "MySQL";
	 //private IDBConnection conn;
	 private String filepath="ITSecurityMapOntology.0.0.2.owl";
	 private OntModel ontmodel;
	 private Hashtable<String, String> relationSet;
	 
	 public DBStore()
	 {
		 relationSet = new Hashtable<String, String>();
	 }
	 
	 public static IDBConnection connect(String strURL, String user, String passwd){
		 
		 try
         {
             Class.forName(strDriver);
         }
         catch(ClassNotFoundException e)
         {
             System.out.println("ClassNotFoundException, Driver is not available");
         }
		 IDBConnection conn = new DBConnection (strURL, user, passwd, strDB); 
		 return conn;
               
	 }
	 
	 public OntModel createDBModelFromFile(IDBConnection conn, String name, File file) throws IOException{
		 
		 ModelMaker maker =  ModelFactory.createModelRDBMaker(conn);
		 Model model = maker.createModel(name);
         FileInputStream fis;
         InputStreamReader isr;
			try {
				 fis = new FileInputStream(file);
			 
		         isr = new InputStreamReader(fis, "UTF-8");  
		         model.read(isr, null);  
		
		         isr.close();  
		         fis.close();  
		         model.commit(); 
	         
			} catch (FileNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} 
			
			ontmodel = ModelFactory.createOntologyModel(new OntModelSpec(OntModelSpec.OWL_DL_MEM), model);
			return ontmodel;
		 
	 }
	 
	 public OntModel getModelFromeDB(IDBConnection conn, String name){
		 ModelMaker maker = ModelFactory.createModelRDBMaker(conn);
		 Model model = maker.getModel(name);
		 OntModelSpec spec;
		 OntModel newmodel = ModelFactory.createOntologyModel(new OntModelSpec(OntModelSpec.OWL_DL_MEM), model);
		 	
		 return newmodel;
		 
	 }
	 
	 public void printClasses(OntModel model){
		 //System.out.println(model);
		 for(ExtendedIterator<OntClass> it = model.listClasses(); it.hasNext();){
			 OntClass oc = it.next();
	 
			 System.out.println(oc.getLocalName() + "---------property");
			 for(ExtendedIterator<OntProperty> its = oc.listDeclaredProperties(); its.hasNext();){
				 OntProperty op = its.next();
				 System.out.println(oc.getLocalName() + "+" + op.getLocalName());
			 }
			 
			 System.out.println(oc.getLocalName() + "---------subclass");
			 for(ExtendedIterator<OntClass> its = oc.listSubClasses(); its.hasNext();){
				 OntClass i = its.next();
				 System.out.println(oc.getLocalName() + "+" + i.getLocalName());
			 }
			 
			 
			 System.out.println("------------------------------------------------------------------");
		 }
	 }
	 
	 public static void createIndiv(OntModel model){
		 String source = "http://www.semanticweb.org/user/ontologies/2014/2/ITSecurityMapOntology.0.0.2#";
		 String ip = "172.18.184.200";
		 OntClass oc = model.getOntClass(source + "Host"); 
		 
		 System.out.println(oc.getLocalName());
		 
		 //create host instance
		 Individual ind = model.createIndividual(source + ip, oc);
		 
		 //create service instance
		 OntClass oc_service = model.getOntClass(source + "Service");
		 Individual ind_sv = oc_service.createIndividual(source + "testFTP");
		
		 
		 OntProperty op = model.getOntProperty(source + "Service");
		 ind.addProperty(op, ind_sv);
//		 ind.addProperty(op, "ftp").addProperty(model.getOntProperty(source + "Info"),"test");	
//		 ind.addProperty(op, "ls");	
		 
		 //test the host instances;
		 for(ExtendedIterator<Individual> its = (ExtendedIterator<Individual>) oc.listInstances();its.hasNext();){
			 Individual iv = its.next();
			 System.out.println(iv);
			 for (StmtIterator si = iv.listProperties(); si.hasNext();) { 
				 StatementImpl sti = (StatementImpl) si.next();  
		            System.out.println(sti.getSubject().getLocalName() + "--"  
		                    + sti.getPredicate().getLocalName() + "--"  
		                    + sti.getObject()); 
			 }
			
		 }
		 
		 
		 //test the service instances
		 
		 for(ExtendedIterator<Individual> its = (ExtendedIterator<Individual>) oc_service.listInstances();its.hasNext();){
			 Individual iv = its.next();
			 System.out.println(iv);
			 for (StmtIterator si = iv.listProperties(); si.hasNext();) { 
				 StatementImpl sti = (StatementImpl) si.next();  
		            System.out.println(sti.getSubject() + "--"  
		                    + sti.getPredicate().getLocalName() + "--"  
		                    + sti.getObject()); 
			 }
			
		 }
	
		 
	 }

	 public void updateModelInDB(IDBConnection conn, String name){
		 ModelMaker maker =  ModelFactory.createModelRDBMaker(conn);
		 Model model = maker.createModel(name);
		 model = ontmodel;		 
		 model.commit();
		 
	 }
	 
	 
	 public void getAllRelationsToHashTable(OntModel model){
		 for(ExtendedIterator<OntClass> it = model.listClasses(); it.hasNext();){
			 OntClass oc1 = it.next();
			 String className1 = oc1.getLocalName();
			 for(ExtendedIterator<OntClass> it2 = model.listClasses(); it2.hasNext();){
				 //两重循环遍历
				 OntClass oc2 = it2.next();
				 String className2 = oc2.getLocalName();
				 String relationship = DBStore.getRelation(model, className1, className2);
				 if(relationship != "null"){
					 String hisRelation = relationSet.get(className1);
					 if(hisRelation == null)
						 hisRelation = className2 + "-" + relationship;
					 else
						 hisRelation = hisRelation + "," + className2 + ":" + relationship;
					 relationSet.put(className1, hisRelation);
					 //relationSet.put(className1 + "-" + className2, relationship);
				 }
			 }
		 }
	 }
	 
	 /** 
	  * Get relation (ObjectPropery) between two classes 
	  *  
	  * @param classname1 
	  * @param classname2 
	  * @return relationValue 
	  */  
	 public static String getRelation(OntModel model, String classname1,  
	         String classname2) {  
	     // Get prefixes  
	     String defaultPrefix = model.getNsPrefixURI("");  
	     String rdfsPrefix = model.getNsPrefixURI("rdfs");  
	     String owlPrefix = model.getNsPrefixURI("owl");  
	   
	     // Create a new query  
	     String queryString = "PREFIX default: <" + defaultPrefix + ">\n"  
	             + "PREFIX rdfs: <" + rdfsPrefix + ">\n" + "PREFIX owl: <"  
	             + owlPrefix + ">\n" + "SELECT ?relation\n"  
	             + "WHERE { ?relation rdfs:domain default:" + classname1  
	             + ".?relation rdfs:range default:" + classname2 + "}";  
	     System.out.println(queryString);
	     // Create the query  
	     Query query = QueryFactory.create(queryString);  
	     // Execute the query and obtain results  
	     QueryExecution qe = QueryExecutionFactory.create(query, model);  
	     ResultSet results = qe.execSelect();  
	   
	     // Get property value  
	     String relationValue;  
	     if (results.hasNext()) {  
	         QuerySolution result = results.nextSolution();  
	         relationValue = result.get("relation").toString()  
	                 .substring(defaultPrefix.length());  
	     } else {  
	         relationValue = null;  
	     }  
	   
	     // Important - free up resources used running the query  
	     qe.close();  
	     return relationValue;  
	 }  
	
	 public static String runSPARQL(OntModel model, String queryStr)
	 {
		 Query query = QueryFactory.create(queryStr);  
	     // Execute the query and obtain results  
	     QueryExecution qe = QueryExecutionFactory.create(query, model);  
	     ResultSet results = qe.execSelect();  
	   
	     // Get property value  
	     StringBuffer sb = new StringBuffer();  
	     while (results.hasNext()) {  
	    	 QuerySolution result = results.nextSolution();
	    	 for(Iterator<String> itr=result.varNames(); itr.hasNext(); )
	    	 {
	    		 String cn = itr.next();
	    		 sb.append(result.get(cn));
	    		 sb.append("\n");
	    	 }
	    	sb.append("\n");
	     } 
	     // Important - free up resources used running the query  
	     qe.close();  
	     return sb.toString();  
	 }
	 /** 
	  * create a individual 
	  * {@code 批量创建基于本体模型的实例 }
	  *  
	  * @param model 本体模型
	  * @param filename 要读瑞的txt文件
	  */  
	 public void createIndiv(OntModel model, String filename, String encoding) { 
		 //tableCollection是分出的表格，其中第一行是label
		 String[] tableCollection = null;
		 String[] tableLabel = null;
		 String NS = model.getNsPrefixURI("");
		 //以下为文件处理部分
		 try{
			 StringBuffer sb = new StringBuffer();
			 //这里涉及到文件编码问题
			 BufferedReader br = new BufferedReader(new BufferedReader(
					 new InputStreamReader(new FileInputStream(filename), encoding)));
			 String line = br.readLine();
			 while(line != null)
			 {
				 sb.append(line);
				 sb.append("\r\n");
				 line = br.readLine();
			 }
			 tableCollection = sb.toString().split("\r\n\r\n");
		 } catch(Exception e) { System.out.println(e.getMessage()); }
		 
		 //提取标签
		 tableLabel = new String[tableCollection.length];
		 for(int i = 0; i < tableLabel.length; i++) {
			 int firstSplit = tableCollection[i].indexOf("\r\n");
			 tableLabel[i] = tableCollection[i].substring(0, firstSplit);
		 }
		 
		//查找某个标签是否是某个类的标签
		 for(int i = 0; i < tableLabel.length; i++){
			 int tableIndex = -1;
			 OntClass oc = null;//用来提取OntClass
			 
			 for(ExtendedIterator<OntClass> it = model.listClasses(); it.hasNext();){
				 oc = it.next();
				 String className = oc.getLocalName();
				 if(className == null) continue;
				 if(tableLabel[i].indexOf(className) != -1){
					 tableIndex = i;
					 break;
				 }
			 }
			 
			 if(tableIndex != -1)
			 {//发现当前label含有对应的类
				 //散列表保存表的属性，以方便查找
				 ArrayList<String> columnName = new ArrayList<String>();
				 ArrayList<ArrayList<String>> table = new ArrayList<ArrayList<String>>();
				 String[] lines = tableCollection[tableIndex].split("\r\n");
				 for(int lineIndex = 1; lineIndex < lines.length; lineIndex++)
				 {//将粒度缩小到单元格
					 String[] line = lines[lineIndex].split("\t");
					 ArrayList<String> tableRow = new ArrayList<String>();
					 for(int j = 0; j < line.length; j++)
					 {
						 tableRow.add(FormatToOriginalSring(line[j]));
						 //System.out.print(FormatToOriginalSring(line[j]));
					 }
					 table.add(tableRow);
					 //System.out.println();
				 }
				 
				 for(int j = 0; j < table.get(0).size(); j++)
				 {
					 columnName.add(table.get(0).get(j));
					 //System.out.println(table.get(0).get(j));
				 }
				 //提取url
				 int urlEnd = tableLabel[tableIndex].indexOf(" —— ");
				 String uri = tableLabel[tableIndex].substring(0, urlEnd);
				 for(int lineIndex = 1; lineIndex < table.size(); lineIndex++)
				 {
					 Individual newoc = oc.createIndividual(uri + table.get(lineIndex).get(0));
					 for(ExtendedIterator<OntProperty> its = oc.listDeclaredProperties(); its.hasNext();){
						 OntProperty op = its.next();
						 String propertyName = op.getLocalName();
						 //System.out.print(propertyName + "\t");
						 Integer propertyindex = null;
						 for(int ci = 0; ci < columnName.size(); ci++)
						 {
							 //System.out.print(columnName.get(ci) + "\t");
							 if(propertyName.indexOf(columnName.get(ci)) != -1 && columnName.get(ci).length() != 0)
							 {
								 //System.out.print(columnName.get(ci).length() + "\t");
								 propertyindex = ci;
								 break;
							 }
						 }
						 if(propertyindex != null)
						 {
							 newoc.addProperty(op, table.get(lineIndex).get(propertyindex));
						 }
					 }
					 Property prop = model.createProperty(NS +"is_Instance_of");//自定义关系：实例
					 model.add(newoc, prop, oc);
					 
					 //关系
					 /*
					 String relations = relationSet.get(oc.getLocalName());
					 if(relations != null)
					 {
						 String[] rela = relations.split(",");
						 for(int j = 0; j < rela.length; j++)
						 {
							 String[] detail = rela[j].split(":");
							 //newoc.getLabel("")
							 prop = model.createProperty(NS+detail[1]);
							 //添加的只是实例与某个类的关系，实际情况应该是实例与实例的关系，这个问题还没解决
							 model.add(newoc, prop, model.getOntClass(NS + detail[0]));
						 }
					 }
					 */
				 }
				 
			 }
		 }
	     //OntClass oc = model.getOntClass("classname");  
	     //Individual individual = oc.createIndividual("individualname");  
	     //OntProperty op = model.getOntProperty(prefix + "propertyname");  
	     //individual.addProperty(op, "propertyvalue");  
	 }
	 
	 public static String FormatToOriginalSring(String fstr)
     {
   	  StringBuffer sb = new StringBuffer();
   	  int length = fstr.length();
   	  int state = 0;//状态码，0为搜索模式，1为斜杠匹配模式
   	  for(int i = 0; i < length; i++)
   	  {
   		  switch(state)
   		  {
   		  case 0:
   			  if(fstr.charAt(i) == '\\')
       		  {
       			  state = 1;
       		  }
       		  else
       		  {
       			  sb.append(fstr.charAt(i));
       		  }
   			  break;
   		  case 1:
       		  if(fstr.charAt(i) == 't')
       		  {
       			  sb.append('\t');
       		  }
       		  else if(fstr.charAt(i) == '\\')
       		  {
       			  sb.append('\\');
       		  }
       		  state = 0;
   			  break;
   		  }
   		 
   	  }
   	  return sb.toString();
     }

}
